package com.chs.recoginition.filter;

import com.alibaba.fastjson.JSONObject;
import com.chs.recoginition.core.config.WebConfig;
import com.chs.recoginition.core.utils.SpringContextUtils;
import com.chs.recoginition.vo.JwtResource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private UserDetailsService userDetailsService;
    private JwtResource jwtResource;
    private WebConfig webConfig;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest req = (HttpServletRequest)request;
        Map<String, Object> map = new HashMap<String, Object>();

        // Get request URL.
        map.put("URL", req.getRequestURL());
        map.put("Method", req.getMethod());
        map.put("Protocol",req.getProtocol());
        // 获取header信息
        List<Map<String, String>> headerList = new ArrayList<>();
        Map<String, String> headerMaps = new HashMap<String, String>();
        for(Enumeration<String> enu = req.getHeaderNames(); enu.hasMoreElements();){
            String name = enu.nextElement();
            headerMaps.put(name,req.getHeader(name));
        }
        headerList.add(headerMaps);
        map.put("headers", headerList);
        //获取parameters信息
        List<Map<String, String>> parameterList = new ArrayList<>();
        Map<String, String> parameterMaps = new HashMap<String, String>();
        for(Enumeration<String> names = req.getParameterNames(); names.hasMoreElements();){
            String name = names.nextElement();
            parameterMaps.put(name, req.getParameter(name));
        }
        parameterList.add(parameterMaps);
        map.put("parameters", parameterList);
        String line = "";
        int idx = req.getRequestURL().indexOf("?");
        if (idx != -1) {
            line = req.getRequestURL().substring(idx + 1);
        } else {
            line = null;
        }
        if (line != null) {
            map.put("Context", new String[] { line });
        }
        System.out.println("请求路径: "+ JSONObject.toJSONString(map.get("URL")));


        init();
        String token = getToken(request);
        String username = jwtResource.getUsernameByToken(token);
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            logger.debug("checking authentication " + username);
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            if (jwtResource.validateToken(token, userDetails.getUsername())) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                logger.debug(" user " + username + ", setting security context");
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }


        chain.doFilter(request, response);
    }

    private String getToken(HttpServletRequest request) {
        return request.getParameter("token");
    }

    private void init() {
        if (userDetailsService == null) {
            synchronized (this) {
                userDetailsService = SpringContextUtils.getBean(UserDetailsService.class);
            }
        }
        if (jwtResource == null) {
            synchronized (this) {
                jwtResource = SpringContextUtils.getBean(JwtResource.class);
            }
        }
        if (webConfig == null) {
            synchronized (this) {
                webConfig = SpringContextUtils.getBean(WebConfig.class);
            }
        }
    }
}
